home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library / Microsoft Programmer's Library (CD-ROM Database)(125-099-008)(Version 1.1a)(CDRM 162100)(1989).iso / SAMPCODE / OS2SDK11 / TK4 / LINEFRAC / LINEFRAC.C < prev    next >
C/C++ Source or Header  |  1989-02-20  |  16KB  |  665 lines

  1. /************************************************************************
  2. *
  3. *   linefrac.c -- Main window procedure for LineFractal window class.
  4. *
  5. *   Created by Microsoft Corporation, 1989
  6. *
  7. ************************************************************************/
  8.  
  9. #define INCL_WIN
  10. #define INCL_GPI
  11. #define INCL_DOSSEMAPHORES
  12. #define INCL_DOSMEMMGR
  13. #define INCL_DOSPROCESS
  14. #include <os2.h>
  15. #include <mt\stdlib.h>
  16.  
  17. #define INCL_GLOBALS
  18. #define INCL_THREADS
  19. #include "linefrac.h"
  20.  
  21. #define INCL_LFMAIN
  22. #define INCL_LFINIT
  23. #define INCL_LFTHREAD
  24. #define INCL_LFPS
  25. #define INCL_LFCMD
  26. #define INCL_LFDRAW
  27. #include "lffuncs.h"
  28.  
  29.  
  30.  
  31.  
  32. /************************************************************************
  33. *
  34. *   Global Variables
  35. *
  36. ************************************************************************/
  37.  
  38. GLOBALDATA global;
  39.  
  40.  
  41.  
  42.  
  43. /************************************************************************
  44. *
  45. *   main
  46. *
  47. *   WinInitialize resizes our ring 2 stack, among other things, so
  48. *   we won't GP fault trying to do graphics.  WinCreateMsgQueue defines
  49. *   us as a REAL PM app. (as does the WINDOWAPI in the .DEF file).
  50. *   Call a subroutine to register our window class and create a window.
  51. *   Loop over messages.  Exit cleanly.
  52. *
  53. ************************************************************************/
  54.  
  55. VOID cdecl
  56. main( VOID )
  57. {
  58.     QMSG qMsg;
  59.     int iRet = 0;
  60.  
  61.     global.hab     = WinInitialize(NULL);
  62.     global.hMsgQ = WinCreateMsgQueue(global.hab, 0);
  63.  
  64.     if (LfInitApp())
  65.     while (WinGetMsg( global.hab, (PQMSG)&qMsg, (HWND)NULL, 0, 0 ))
  66.         WinDispatchMsg( global.hab, (PQMSG)&qMsg );
  67.     else
  68.     iRet = -1;
  69.  
  70.     WinDestroyWindow( global.hwndFrame );
  71.     WinDestroyMsgQueue( global.hMsgQ );
  72.     WinTerminate( global.hab );
  73.     DosExit(EXIT_PROCESS, iRet);
  74. }
  75.  
  76.  
  77.  
  78.  
  79. /************************************************************************
  80. *
  81. *   LineFracWndProc
  82. *
  83. *   Process messages for the LineFractal window class.
  84. *
  85. ************************************************************************/
  86.  
  87. ULONG CALLBACK
  88. LineFracWndProc( hwnd, usMsg, mp1, mp2 )
  89. HWND   hwnd;
  90. USHORT usMsg;
  91. MPARAM  mp1;
  92. MPARAM  mp2;
  93. {
  94.     HPS     hps;
  95.     USHORT  iNewTop;
  96.     int     i;
  97.     PTHR pthr;
  98.     RECTL rcl;
  99.     BOOL  fIsTimerUsed;
  100.  
  101.     switch (usMsg)
  102.     {
  103.     case WM_CREATE:
  104.     if ((global.hptr)[global.usCurPtr])
  105.         WinSetPointer(HWND_DESKTOP,(global.hptr)[global.usCurPtr]);
  106.     break;
  107.  
  108.     case WM_CLOSE:
  109.     LfClose(hwnd);
  110.     break;
  111.  
  112.     case WM_COMMAND:
  113.     LfCommand(hwnd, LOUSHORT(mp1));
  114.     break;
  115.  
  116.     case WM_TIMER:
  117.     if (LOUSHORT(mp1) == IDT_AUTOSTARTREDRAW)
  118.     {
  119.         fIsTimerUsed = FALSE;
  120.         for (i = 0; i < global.cThr; ++i)
  121.         if (global.aThr[i]->fAutoStartRedraw)
  122.         {
  123.             DosSemClear(&(global.aThr[i])->lSemRedraw);
  124.             fIsTimerUsed = TRUE;
  125.         }
  126.         if (!fIsTimerUsed)
  127.         LfStopRedrawTimer();
  128.         else
  129.         {
  130.         LfStopRedrawTimer();
  131.         LfStartRedrawTimer();
  132.         }
  133.     }
  134.     else if (LOUSHORT(mp1) == IDT_AUTOSWITCH)
  135.     {
  136.         DosEnterCritSec();
  137.         iNewTop = (global.iThrTop + 1) % global.cThr;
  138.         DosExitCritSec();
  139.         LfBringThreadToTop(global.aThr[iNewTop]);
  140.     }
  141.     else
  142.         goto pass_it_on;
  143.     break;
  144.  
  145.     case WM_ERASEBACKGROUND:
  146.     LfEraseBackground(hwnd, NULL, NULL, NULL);
  147.     return FALSE;
  148.     break;
  149.  
  150.     case WM_PAINT:
  151.     if (!global.pThrTop)
  152.         WinSendMsg(hwnd, WM_COMMAND, (MPARAM)IDM_DCMEMORY, 0);
  153.  
  154.     hps = WinBeginPaint(global.hwnd, NULL, &rcl);
  155.     if (global.pThrTop)   /* only try to paint if we have a drawing */
  156.         LfPaint(hps, &rcl);
  157.     WinEndPaint(hps);
  158.     break;
  159.  
  160.     case WM_CHAR:
  161.     if (LOUSHORT(mp1) & KC_CHAR)
  162.         LfChar(hwnd, (char)mp2);
  163.     break;
  164.  
  165.     case WM_BUTTON1DOWN:
  166.     case WM_BUTTON2DOWN:
  167.     LfButtonDown(hwnd, mp1);
  168.     WinSetFocus(HWND_DESKTOP, hwnd);
  169.     break;
  170.  
  171.     case WM_BUTTON1UP:
  172.     case WM_BUTTON2UP:
  173.     LfButtonUp(usMsg);
  174.     break;
  175.  
  176.     case WM_MOUSEMOVE:
  177.     LfMouseMove();
  178.     break;
  179.  
  180.     case WM_SIZE:
  181.     /* Resize each PS that has fAutoSizePS set to TRUE. */
  182.  
  183.     WinQueryWindowRect(global.hwnd, &global.rcl);
  184.     global.bm.cx = (USHORT) (global.rcl.xRight - global.rcl.xLeft);
  185.     global.bm.cy = (USHORT) (global.rcl.yTop   - global.rcl.yBottom);
  186.  
  187.     for (i = 0; i < global.cThr; ++i)
  188.         if (pthr = global.aThr[i])
  189.         if (pthr->hps)
  190.             if (pthr->fAutoSizePS)
  191.             {
  192.             global.bm.cPlanes   = pthr->cPlanes;
  193.             global.bm.cBitCount = pthr->cBitCount;
  194.  
  195.             if (LfResizePS(pthr))
  196.                 DosSemClear(&pthr->lSemRedraw);
  197.             }
  198.  
  199.     /* fall through -- we might want to restart point accumulation,
  200.        but don't want to process the resize message */
  201.  
  202.     default:
  203. pass_it_on:
  204.     return( (ULONG)WinDefWindowProc(hwnd, usMsg, mp1, mp2));
  205.     break;
  206.     }
  207.  
  208.     return FALSE;
  209. }
  210.  
  211.  
  212.  
  213.  
  214. /************************************************************************
  215. *
  216. *   LfClose
  217. *
  218. *   Kill all the threads still running and delete all our fancy pointers.
  219. *   In general, prepare to terminate the program.
  220. *
  221. ************************************************************************/
  222.  
  223. VOID
  224. LfClose(hwnd)
  225. HWND hwnd;
  226. {
  227.     int i;
  228.  
  229.     WinSendMsg(hwnd, WM_COMMAND, (MPARAM)IDM_KILLALLTHREADS, 0);
  230.     WinSetPointer(HWND_DESKTOP,
  231.           WinQuerySysPointer(HWND_DESKTOP,SPTR_ARROW,FALSE));
  232.     for (i = 0; i < NUM_PTR_SHAPES; ++i)
  233.     if ((global.hptr)[i])
  234.         WinDestroyPointer((global.hptr)[i]);
  235.     if (global.hptrTrack)
  236.     WinDestroyPointer(global.hptrTrack);
  237.     if (global.hptrPaste)
  238.     WinDestroyPointer(global.hptrPaste);
  239.     WinPostMsg(hwnd, WM_QUIT, 0L, 0L);
  240. }
  241.  
  242.  
  243.  
  244.  
  245. /************************************************************************
  246. *
  247. *   LfEraseBackground
  248. *
  249. *   Erase the window background to a hatch pattern.  This enables the
  250. *   user to see where the bitmap's edges are in case it's smaller
  251. *   than the window.
  252. *
  253. ************************************************************************/
  254.  
  255. VOID
  256. LfEraseBackground(hwnd, hpsCaller, prclUpdate, prclX)
  257. HWND hwnd;
  258. HPS hpsCaller;
  259. PRECTL prclUpdate;
  260. PRECTL prclX;    /* excluded rectangle */
  261. {
  262.     HPS hps;
  263.     RECTL rcl;
  264.     RECTL rclT;
  265.     AREABUNDLE ab;
  266.     HRGN hrgnClipOld;
  267.     HRGN hrgn;
  268.     HRGN hrgnT;
  269.  
  270.  
  271.     if (hpsCaller)
  272.     hps = hpsCaller;
  273.     else
  274.     hps = WinGetPS(hwnd);
  275.  
  276.     if (prclUpdate)
  277.     rcl = *prclUpdate;
  278.     else
  279.     WinQueryUpdateRect(hwnd, (PRECTL)&rcl);
  280.  
  281.     ab.lColor      = CLR_BLACK;
  282.     ab.lBackColor = CLR_WHITE;
  283.     ab.usSymbol   = PATSYM_DIAG1;
  284.     GpiSetAttrs(hps, PRIM_AREA, ABB_COLOR|ABB_BACK_COLOR|ABB_SYMBOL,
  285.         0L, (PBUNDLE)&ab);
  286.  
  287.  
  288.     /* Make a region out of the nearest rectangle, then copy the real
  289.      * region data into it.  Set this as our clip rectangle.
  290.      */
  291.     if ((hrgn = GpiCreateRegion(hps, 1L, &rcl)) != HRGN_ERROR)
  292.     {
  293.     WinQueryUpdateRegion(hwnd, hrgn);
  294.     GpiSetClipRegion(hps, hrgn, &hrgnClipOld);
  295.     }
  296.  
  297.     if (!prclX)
  298.     GpiBitBlt(hps, NULL, 2L, (PPOINTL)&rcl, ROP_PATCOPY, NULL);
  299.     else
  300.     {
  301.     if (prclX->yTop < rcl.yTop)
  302.     {
  303.         rclT.xLeft     = rcl.xLeft;
  304.         rclT.yBottom = prclX->yBottom;
  305.         rclT.xRight  = rcl.xRight;
  306.         rclT.yTop     = rcl.yTop;
  307.         GpiBitBlt(hps, NULL, 2L, (PPOINTL)&rclT, ROP_PATCOPY, NULL);
  308.     }
  309.  
  310.     if (prclX->xRight < rcl.xRight)
  311.     {
  312.         rclT.xLeft     = prclX->xRight;
  313.         rclT.yBottom = rcl.yBottom;
  314.         rclT.xRight  = rcl.xRight;
  315.         rclT.yTop     = prclX->yTop;
  316.         GpiBitBlt(hps, NULL, 2L, (PPOINTL)&rclT, ROP_PATCOPY, NULL);
  317.     }
  318.     }
  319.  
  320.     if (hrgnClipOld != HRGN_ERROR)
  321.     GpiSetClipRegion(hps, hrgnClipOld, &hrgnT);
  322.     if (hrgn != HRGN_ERROR)
  323.     GpiDestroyRegion(hps, hrgn);
  324.  
  325.     if (!hpsCaller)
  326.     WinReleasePS(hps);
  327. }
  328.  
  329.  
  330.  
  331.  
  332. /************************************************************************
  333. *
  334. *   LfPaint
  335. *
  336. *   If we have a bitmap, blt it to the screen, no matter what state
  337. *   it's in.  If the selection rectangle is still alive, then display
  338. *   it, too.  Note that it goes directly to the screen, so we have to
  339. *   redraw it each time the bitmap is thrown back up.
  340. *
  341. ************************************************************************/
  342.  
  343. VOID
  344. LfPaint(hps, prcl)
  345. HPS  hps;
  346. PRECTL prcl;
  347. {
  348.     POINTL  aptl[4];
  349.  
  350.     if (global.pThrTop)
  351.     {
  352.     switch (global.pThrTop->dcType)
  353.     {
  354.     case IDM_DCDIRECT:    /* all drawing is already on the screen */
  355.         break;
  356.  
  357.     case IDM_DCPOSTSCRIPT:
  358.     case IDM_DCPROPRINTER:
  359.         break;
  360.  
  361.     case IDM_DCMEMORY:
  362.  
  363.         GpiSetAttrs(hps, PRIM_IMAGE, IBB_COLOR|IBB_BACK_COLOR, 0L, &global.pThrTop->ib);
  364.  
  365.         aptl[0].x = 0L;
  366.         aptl[0].y = 0L;
  367.         aptl[1].x = (global.pThrTop->rcl).xRight;
  368.         aptl[1].y = (global.pThrTop->rcl).yTop;
  369.         aptl[2].x = 0L;
  370.         aptl[2].y = 0L;
  371.  
  372.         GpiBitBlt(hps, global.pThrTop->hps, 3L, aptl, ROP_SRCCOPY, (LONG)NULL);
  373.         LfEraseBackground(global.hwnd, hps, prcl, &(global.pThrTop->rcl));
  374.         break;
  375.  
  376.     default:
  377.         break;
  378.     }
  379.     if (global.fShowSelectRc)
  380.         LfShowSelectRc(hps, global.fTempSelect ? &global.rclSelect : &global.rclCutCopy);
  381.     }
  382. }
  383.  
  384.  
  385.  
  386.  
  387. /************************************************************************
  388. *
  389. *   LfShowSelectRc
  390. *
  391. *   Draw the selection rectangle in the given presentation space.  The
  392. *   rectangle is drawn in xor-mode so this can be called to remove it
  393. *   as well as show it.
  394. *
  395. ************************************************************************/
  396.  
  397. VOID
  398. LfShowSelectRc(hps, lprc)
  399. HPS hps;
  400. PRECTL lprc;
  401. {
  402.     LINEBUNDLE lb;
  403.  
  404.  
  405.     lb.lColor     = CLR_TRUE;
  406.     lb.usMixMode = FM_XOR;
  407.     lb.usType     = LINETYPE_ALTERNATE;
  408.     GpiSetAttrs(hps, PRIM_LINE, LBB_COLOR|LBB_MIX_MODE|LBB_TYPE,
  409.         0L, (PBUNDLE)&lb);
  410.     GpiSetCurrentPosition(hps, (POINTL *)&(lprc->xLeft));
  411.     GpiBox(hps, DRO_OUTLINE, (POINTL *)&(lprc->xRight), 0L, 0L);
  412. }
  413.  
  414.  
  415.  
  416.  
  417. /************************************************************************
  418. *
  419. *   LfChar
  420. *
  421. *   Handle LineFractal's keyboard interface.  This consists of:
  422. *
  423. *   <space>    Cancels the selection rectangle.
  424. *   0-9     Brings thread i to the top, if it exists.
  425. *
  426. ************************************************************************/
  427.  
  428. VOID
  429. LfChar(hwnd, ch)
  430. HWND hwnd;
  431. char ch;
  432. {
  433.     HPS hps;
  434.     PRECTL lprc;
  435.     int i;
  436.  
  437.     if (ch == ' ')
  438.     {
  439.     if (global.fShowSelectRc)
  440.     {
  441.         global.fShowSelectRc = FALSE;
  442.         hps = WinGetPS(hwnd);
  443.         if (global.fTempSelect)
  444.         {
  445.         lprc = &global.rclSelect;
  446.         global.fTempSelect = FALSE;
  447.         }
  448.         else
  449.         lprc = &global.rclCutCopy;
  450.         LfShowSelectRc(hps, lprc);
  451.         WinReleasePS(hps);
  452.     }
  453.     }
  454.     else if (ch >= '0' && ch <= '9')
  455.     {
  456.     i = ch - '0';
  457.     if (i < global.cThr)
  458.         LfBringThreadToTop(global.aThr[i]);
  459.     }
  460. }
  461.  
  462.  
  463.  
  464.  
  465. /************************************************************************
  466. *
  467. *   LfMouseMove
  468. *
  469. *   Handle actions necessary upon each move of the mouse pointer.
  470. *   This consists of resetting the mouse pointer -- if we pass
  471. *   this on to WinDefWindowProc, it will reset it to the arrow.
  472. *   As long as we're setting the pointer so often, we can do a
  473. *   little animation.
  474. *
  475. ************************************************************************/
  476.  
  477. VOID
  478. LfMouseMove()
  479. {
  480.     /* Do this so that if in tracking mode, the correct pointer
  481.        shape appears immediately. */
  482.     if (global.fTracking || global.fSelecting)
  483.     {
  484.     if (global.hptrTrack)
  485.         WinSetPointer(HWND_DESKTOP,global.hptrTrack);
  486.     return;
  487.     }
  488.     if (global.fPasting)
  489.     {
  490.     if (global.hptrPaste)
  491.         WinSetPointer(HWND_DESKTOP,global.hptrPaste);
  492.     return;
  493.     }
  494.     if (global.pThrTop)
  495.     {
  496.      if (global.pThrTop->fBusy)
  497.      {
  498.         if (global.hptrWait)
  499.         WinSetPointer(HWND_DESKTOP,global.hptrWait);
  500.         return;
  501.      }
  502.     }
  503.     global.usPtrCounter = (global.usPtrCounter+1) % global.usPtrThreshold;
  504.     if (global.usPtrCounter == 0)
  505.     {
  506.     global.usCurPtr += global.usPtrIncr;
  507.     if (global.usCurPtr <= 0)
  508.         global.usCurPtr = 0;
  509.     else
  510.         global.usCurPtr %= NUM_PTR_SHAPES;
  511.     if ((global.usCurPtr == NUM_PTR_SHAPES - 1) ||
  512.         (global.usCurPtr == 0))
  513.         global.usPtrIncr *= -1;
  514.     }
  515.     if ((global.hptr)[global.usCurPtr])
  516.     WinSetPointer(HWND_DESKTOP,(global.hptr)[global.usCurPtr]);
  517. }
  518.  
  519.  
  520.  
  521.  
  522. /************************************************************************
  523. *
  524. *   LfButtonUp
  525. *
  526. *   Handle up clicks of the mouse buttons.  This consists of:
  527. *
  528. *   left button up    increase the depth of recursion
  529. *   right button up    decrease the depth of recursion
  530. *
  531. *            In both cases, clear the semaphore so the
  532. *            drawing can restart at the new level of
  533. *            recursion.
  534. *
  535. ************************************************************************/
  536.  
  537. VOID
  538. LfButtonUp(usMsg)
  539. USHORT usMsg;
  540. {
  541.     if (global.fMouseChangesRecursion)
  542.     {
  543.     if (usMsg == WM_BUTTON1UP)
  544.         global.pThrTop->usRecursion = ++global.pThrTop->usRecursion;
  545.     else if (global.pThrTop->usRecursion > 0)
  546.         global.pThrTop->usRecursion = --global.pThrTop->usRecursion;
  547.  
  548.     global.pThrTop->flMiscAttrs |= LFA_RECURSION;
  549.     global.pThrTop->fUpdateAttrs = TRUE;
  550.     global.fUpdateAttrs = TRUE;
  551.  
  552.     if (global.pThrTop->hps)
  553.     {
  554.         global.pThrTop->fInterrupted = TRUE;
  555.         DosSemClear(&(global.pThrTop)->lSemRedraw);
  556.     }
  557.     }
  558. }
  559.  
  560.  
  561.  
  562.  
  563. /************************************************************************
  564. *
  565. *   LfButtonDown
  566. *
  567. *   Handle down clicks of the mouse buttons.  This consists of
  568. *   changing the mouse pointer depending upon which mode we're in
  569. *   and calling off to the subroutine to do the real work given
  570. *   the position at which the mouse button was clicked.  The modes
  571. *   are "tracking", "selecting", and "pasting".  Tracking means the
  572. *   user is defining the new dimensions of the fractal.  Selecting
  573. *   means the user is dragging a rectangle to cut or copy.  Pasting
  574. *   means the user is positioning the cut or copied rectangle in
  575. *   the window.
  576. *
  577. ************************************************************************/
  578.  
  579. VOID
  580. LfButtonDown(hwnd, mp1)
  581. HWND hwnd;
  582. MPARAM mp1;
  583. {
  584.     POINTS pt;
  585.  
  586.     if (global.fTracking)
  587.     {
  588.     if (global.hptrTrack)
  589.         WinSetPointer(HWND_DESKTOP,global.hptrTrack);
  590.     pt.x = LOUSHORT(mp1);
  591.     pt.y = HIUSHORT(mp1);
  592.     LfSelectDimension(hwnd, pt);
  593.     global.fTracking = FALSE;
  594.     if ((global.hptr)[global.usCurPtr])
  595.         WinSetPointer(HWND_DESKTOP,(global.hptr)[global.usCurPtr]);
  596.     if (global.pThrTop->fAttrRedraw)
  597.     {
  598.         global.pThrTop->fInterrupted = TRUE;
  599.         DosSemClear(&(global.pThrTop)->lSemRedraw);
  600.     }
  601.     }
  602.     else if (global.fSelecting)
  603.     {
  604.     if (global.hptrTrack)
  605.         WinSetPointer(HWND_DESKTOP,global.hptrTrack);
  606.     pt.x = LOUSHORT(mp1);
  607.     pt.y = HIUSHORT(mp1);
  608.     LfSelect(hwnd, pt);
  609.     global.fSelecting = FALSE;
  610.     if ((global.hptr)[global.usCurPtr])
  611.         WinSetPointer(HWND_DESKTOP,(global.hptr)[global.usCurPtr]);
  612.     }
  613.     else if (global.fPasting)
  614.     {
  615.     if (global.hptrPaste)
  616.         WinSetPointer(HWND_DESKTOP,global.hptrPaste);
  617.     pt.x = LOUSHORT(mp1);
  618.     pt.y = HIUSHORT(mp1);
  619.     LfPaste(hwnd);
  620.     global.fPasting = FALSE;
  621.     if ((global.hptr)[global.usCurPtr])
  622.         WinSetPointer(HWND_DESKTOP,(global.hptr)[global.usCurPtr]);
  623.     }
  624. }
  625.  
  626.  
  627.  
  628.  
  629. /************************************************************************
  630. *
  631. *   LfStartRedrawTimer
  632. *
  633. ************************************************************************/
  634.  
  635. VOID
  636. LfStartRedrawTimer()
  637. {
  638.     USHORT timeout;
  639.  
  640.     if (!global.fTimerOn)
  641.     {
  642.     timeout = (USHORT) ((rand()/32767.0) *
  643.           (global.usMaxTimerDelay  - global.usMinTimerDelay) +
  644.            global.usMinTimerDelay);
  645.     WinStartTimer(global.hab, global.hwnd, IDT_AUTOSTARTREDRAW, timeout);
  646.     global.fTimerOn = TRUE;
  647.     }
  648. }
  649.  
  650.  
  651.  
  652.  
  653. /************************************************************************
  654. *
  655. *   LfStopRedrawTimer
  656. *
  657. ************************************************************************/
  658.  
  659. VOID
  660. LfStopRedrawTimer()
  661. {
  662.     WinStopTimer(global.hab, global.hwnd, IDT_AUTOSTARTREDRAW);
  663.     global.fTimerOn = FALSE;
  664. }
  665.